import React from "react"
import { withRouter } from 'react-router-dom'
import axios from "axios";
import "../css/page.css"

class Component extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      status: null,
      model: {},
      trainingData: {},
      feedforwardData: {},
      timer: 0
    }
    this.click = this.click.bind(this);
    this.flushStatus = this.flushStatus.bind(this);
    this.renderStatus = this.renderStatus.bind(this);
    this.handleModelChnage = this.handleModelChnage.bind(this);
    this.handleFeedforwardDataChnage = this.handleFeedforwardDataChnage.bind(this);
    this.handleTrainingDataChnage = this.handleTrainingDataChnage.bind(this);
    this.handleModelCreate = this.handleModelCreate.bind(this);
    this.handleFeeforward = this.handleFeeforward.bind(this);
    this.handleTrain = this.handleTrain.bind(this);
  }

  componentDidMount() {
    this.flushStatus();
    this.setState({
      timer: setInterval(() => {
        this.flushStatus();
      }, 500)
    });
  }

  componentWillUnmount() {
    clearInterval(this.state.timer);
  }

  handleFeedforwardDataChnage(id) {
    return (e) => {
      this.setState(state => {
        return { feedforwardData: { ...state.feedforwardData, [id]: e.target.value } };
      });
    }
  }

  handleTrainingDataChnage(id) {
    return (e) => {
      this.setState(state => {
        return { trainingData: { ...state.trainingData, [id]: e.target.value } };
      });
    }
  }

  handleModelChnage(id) {
    return (e) => {
      this.setState(state => {
        return { model: { ...state.model, [id]: e.target.value } };
      });
    }
  }

  handleModelCreate(id) {
    return (e) => {
      e.preventDefault();
      let model = this.state.model[id];
      if (model) {
        // shape,size,activation | shape,size,activation | ...
        let loss = model.split('&')[1] ? model.split('&')[0] : undefined;
        let networkConfig = model.split('l')[1] ?
          model.split('&')[1].split('|').map(t => t.split(',')).map(t => t.map(c => c.trim())) :
          model.split('|').map(t => t.split(',')).map(t => t.map(c => c.trim()));
        networkConfig = networkConfig.map(t => [Number(t[0]), Number(t[1]), t[2]]);
        let request = { layers: JSON.stringify(networkConfig), loss: loss, threadId: id };
        axios.post('/ml/createModel', request).then((res) => {
          if (res.data.status === 1) {
            alert(`created model on thread${id} succeed`);
          }
        })
      }
    }
  }

  handleFeeforward(id) {
    return (e) => {
      e.preventDefault();
      let data = this.state.feedforwardData[id];
      if (data) {
        let t = JSON.stringify(eval(`(()=>${data})()`));
        let request = { data: t, threadId: id };
        axios.post('/ml/feedforward', request).then((res) => {
          if (res.data.status === 1) {
            alert('computed');
          }
        })
      }
    }
  }

  handleTrain(id) {
    return (e) => {
      e.preventDefault();
      let data = this.state.trainingData[id];
      if (data) {
        let td = data.split('/')[2].split(',').map(p => {
          let t = p.split('|');
          let i = t[0];
          let o = t[1];
          return { input: eval(i), output: eval(o) };
        });
        let lr = Number(data.split('/')[1].trim());
        let time = Number(data.split('/')[0].trim());
        let request = { data: JSON.stringify(td), threadId: id, time, lr };
        axios.post('/ml/train', request).then((res) => {
          if (res.data.status === 1) {
            alert('start train');
          }
        })
      }
    }
  }

  click(e) {
    e.preventDefault();
    this.flushStatus();
  }

  flushStatus() {
    axios.get('/ml/status').then((res) => {
      this.setState({ status: res.data });
    });
  }

  renderStatus() {
    if (this.state.status) {
      let result = this.state.status.workers.map(worker => {
        return (
          <li key={worker.threadId}>
            <ul>
              {
                Object.keys(worker).map(k => {
                  return <li key={worker.threadId + k}>{k}: <span>{worker[k] !== null ? worker[k].toString() : 'null'}</span></li>
                })
              }
            </ul>
            <input placeholder="network config" onChange={this.handleModelChnage(worker.threadId)} />
            <button onClick={this.handleModelCreate(worker.threadId)}>create model</button>
            <br />
            <input placeholder="training data" onChange={this.handleTrainingDataChnage(worker.threadId)} />
            <button onClick={this.handleTrain(worker.threadId)}>train</button>
            <br />
            <input placeholder="feed data" onChange={this.handleFeedforwardDataChnage(worker.threadId)} />
            <button onClick={this.handleFeeforward(worker.threadId)}>feedforward</button>
            <hr></hr>
          </li>
        )
      })
      return (
        <ul>
          {result}
        </ul>
      )
    } else {
      return undefined
    }

  }

  render() {
    return (
      <div id="index">
        <div id="status">
          <span>status: </span><button onClick={this.click}>flush status</button>
          {this.renderStatus()}
        </div>
      </div>
    )
  }
}

export default withRouter(Component)
